package com.sailing.xjpb.common.io;

import com.sailing.xjpb.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import sun.nio.cs.ext.GBK;

import java.io.BufferedInputStream;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.EnumSet;
import java.util.Set;

/**
 * 对安全基线V1.0要求，需要对用户上传的文件权限不超过640、文件夹权限不超过750
 *
 * @author YaoWei
 * createDate: 2022-5-19
 */
@Slf4j
public final class SailingFileUtils {

    private SailingFileUtils() {

    }

    /**
     * 创建文件夹并且授权640
     *
     * @param path 文件路径
     * @return 文件信息
     */
    public static String forceMkdirs(String path) {
        File file = new File(path);
        if (!file.exists() && file.mkdirs()) {
            setDefaultPermission(file);
        }
        return file.getAbsolutePath();
    }

    /**
     * 设置文件默认的权限：600
     *
     * @param file 上传的文件信息
     */
    public static void setDefaultPermission(File file) {
        try {
            String os = System.getProperty("os.name");
            if (os != null && os.toLowerCase().startsWith("linux")) {
                Set<PosixFilePermission> perms = EnumSet.of(PosixFilePermission.OWNER_READ,
                        PosixFilePermission.OWNER_WRITE, PosixFilePermission.GROUP_READ);
                Path path = Paths.get(file.getAbsolutePath());
                Files.setPosixFilePermissions(path, perms);
                log.info("安全基线要求的文件权限：{} 设置成功！", perms);
            }
        } catch (Exception e) {
            log.warn("Change folder " + file.getAbsolutePath() + " permission failed.", e);
        }
    }

    /**
     * 获取转码后的文件名称-防止乱码
     *
     * @param fileName 文件名称
     * @return 转码后的文件名称
     */
    public static String doEncode(String fileName) {
        if (StandardCharsets.ISO_8859_1.newEncoder().canEncode(fileName)) {
            fileName = new String(fileName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        }
        return fileName;
    }

    /**
     * Description: 获取文件的编码格式
     *
     * @param file 文件
     * @return java.nio.charset.Charset
     * author: wangbo
     */
    public static Charset fileCharset(File file) {
        try (BufferedInputStream bin = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
            Charset charset;
            int p = (bin.read() << 8) + bin.read();
            switch (p) {
                case 0xefbb:
                    charset = StandardCharsets.UTF_8;
                    break;
                case 0xfffe:
                    charset = StandardCharsets.US_ASCII;
                    break;
                case 0xfeff:
                    charset = StandardCharsets.UTF_16BE;
                    break;
                default:
                    charset = new GBK();
            }
            return charset;
        } catch (Exception e) {
            log.warn("读取文件格式错误，将返回默认GBK编码", e);
            return new GBK();
        }
    }

    /**
     * Description: 获取文件的编码格式
     *
     * @param filePath 文件全路径
     * @return java.nio.charset.Charset
     * author: wangbo
     */
    public static Charset fileCharset(String filePath) {
        File file = new File(filePath);
        if (file.isDirectory()) {
            throw BusinessException.businessError(filePath + "不是文件地址");
        }
        return fileCharset(file);
    }
}
